home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 121_01 / sh.c < prev    next >
Text File  |  1985-08-19  |  15KB  |  714 lines

  1. /*
  2. HEADER: CUG 121.??;
  3.  
  4.     TITLE:    sh - a 'little shell' command interpreter;
  5.     VERSION:    2.2;
  6.     DATE:    01/06/86;
  7.     DESCRIPTION: "The little shell is designed to provide a `Unix-like'
  8.         shell for CP/M, replacing the CP/M CCP as the primary user
  9.         interface.  It provides two convenient mechanisms for
  10.         chaining commands together: they may be typed on a single
  11.         line, separated by commas; or files of commands called Shell
  12.         scripts may be executed.
  13.         The CP/M operating environment does not lend itself to the
  14.         use of frequently invoked commands in the form of executable
  15.         files.  Consequently, the shell has an extensive array of
  16.         built-in commands, including: cat, ccp, cd, clr, echo, exit,
  17.         lock, logout, ls, pwd, ren, rm, sleep, unlock.
  18.         The above is accomplished at a cost:  the shell is written in
  19.         BDS C and is five times the size of the CP/M CCP; hence it
  20.         takes somewhat longer to load into memory at warm boots.
  21.         Also, since the shell clobbers the CCP, submit does not work
  22.         when the shell is invoked.";
  23.     KEYWORDS:    shell, command, interpreter;
  24.     SYSTEM:    CP/M;
  25.     FILENAME:    SH.C;
  26.     WARNINGS:    "Copyright (c) 1982 Steve Blasingame.
  27.         Requires doglob.h and fcb.h for compile.";
  28.     AUTHORS:    Steve Blasingame;
  29.     COMPILERS:    BDS-C 1.50;
  30. */
  31.  
  32. #include <bdscio.h>
  33. #include <hardware.h>
  34. #include "fcb.h"
  35. #include "doglob.h"
  36.  
  37. #define    EOT    4    /* ascii eot */
  38. #define    PROMPT    "$ "    /* prompt string */
  39. #define TABSIZE    7    /* spaces in a tab */
  40. #define    CNTLH    8    /* backspace */
  41. #define DEL    0x7f    /* ascii del */
  42. #define QUIT    0x1c    /* cntl-backslash */
  43. #define LINEKILL 24    /* cntl-x */
  44. #define    SLEEPNO    16    /* sleep constant for 4 Mz Z80a */
  45. #define COMMENT    '#'    /* comment line */
  46. #define    stdin    0    /* for console io */
  47. #define    stdout    1    /* for console io */
  48. #define    FILE    struct _buf
  49. #define SHBUF    0xf54b    /* Buffer in current bios */
  50. char    combuf[MAXLINE]; /* command line buffer */
  51. char    globs[GLOBMAX*FILENAMESIZE]; /* expansion buffer */
  52. int    argvp[20];    /* array of argument pointers */
  53. int    argcp;        /* argument count for execv */
  54. int    testmode;    /* verbose flag */
  55. int    flag;        /* for lst function */
  56.  
  57. /* Structure of Shell's Storage Area in the CBIOS */
  58. struct    exbuf    {
  59.     char    _shdsk;        /* current directory */
  60.     int    _shsav;        /* buffer save flag  */
  61.     char    _nocli;        /* no shell option */
  62.     char    _shbuf[BUFSIZ]; /* buffer */
  63. };
  64.  
  65. struct exbuf *iop;        /* pointer to bios buffer */
  66. int    parse();        /* parse command line */
  67. int    dolocal();        /* do built-in shell commands */
  68. int    lexecv();        /* local execv until C1.45a */
  69. char    *b_gets();        /* local crt driver */
  70. char    pwd();            /* return current logical disk */
  71. char    chdir();        /* select disk */
  72. int    filprt();        /* list selected file on screen */
  73. int    lst();            /* format directory listing */
  74. int    dofile();        /* process shell script */
  75. int    flock();        /* lock or unlock file */
  76. int    doshell();        /* exec the shell */
  77. int    expand();        /* expand global filenames */
  78. int    dozap();        /* interactively delete files */
  79. int    doglob();        /* parse global file expressions */
  80. int    more();            /* list multiple files on screen */
  81. int    crfil();        /* fill memory */
  82. int    strcmp();
  83.  
  84. main(argc,argv)
  85. int argc;
  86. char *argv[];
  87. {
  88. char *cp;
  89.  
  90. _allocp = 0;    /* initializer */
  91. iop = SHBUF;    /* initializer */
  92. testmode = 0;    /* initializer */
  93. iop->_nocli = 0;    /* default shell on reboot */
  94. if (argc == 2 && (strcmp(argv[1],"-T") == 0)) testmode =1;
  95. if (argc == 3 && (strcmp(argv[1],"-F") == 0)) parse(strlower(argv[2]));
  96.  
  97.  
  98.     bdos(0x0e, iop->_shdsk);    /* restore cwd */
  99.  
  100.     while (1) {
  101.         crfil(combuf,MAXLINE,0);
  102.         if (!iop->_shsav) {
  103.             puts(PROMPT);
  104.             if (!b_gets(combuf))
  105.                 break;
  106.             else {
  107.                 cp = combuf;
  108.                 if (parse(cp) == -1)
  109.                     puts("what?\n");
  110.             }
  111.         }
  112.         else {
  113.             strcpy(combuf,&iop->_shbuf);
  114.             iop->_shsav = 0;
  115.             cp = combuf;
  116.             if (parse(cp) == -1)
  117.                 puts("syntax error\n");
  118.         }
  119.     }
  120. chdir('a');            /* home directory */
  121. if (execl("a:login",0) == -1)    /* admittedly a kluge */
  122.     ;
  123. doshell();
  124. }
  125. parse(cp)
  126. char *cp;
  127. {
  128. int i;
  129. char    *pointer;
  130. i=0;
  131. argvp[i]=cp;
  132.  
  133.     if (testmode) puts(cp);
  134.     if (*cp == '\n')
  135.         return 0;
  136.     else {
  137.         while(*cp == ' ')    /* skip blanks */
  138.             cp++;
  139.         argvp[i]=cp;
  140.         while(*++cp != NULL) {
  141.             if (*cp == ' ') {
  142.                 i++;
  143.                 *cp = NULL;
  144.                 argvp[i]=cp+1;
  145.             }
  146.             else if (*cp == ';') {
  147.                 if (cp == combuf || *(cp+1) != ' ')
  148.                     return -1;
  149.                 else {
  150.                     i++;
  151.                     *cp = NULL;
  152.                     argvp[i]=NULL;
  153.                     cp += 2;
  154.                     strcpy(iop->_shbuf,cp);
  155.                     iop->_shsav = 1;
  156.                     break;
  157.                 }
  158.             }
  159.             else if (*cp == '\n') {
  160.                 i++;
  161.                 *cp = NULL;
  162.                 argvp[i]=NULL;
  163.                 break;
  164.             }
  165.         }
  166.     argcp = 0;
  167.     while(1) {
  168.         if (!argvp[argcp]) break;
  169.         argcp++;
  170.     }
  171.     if (dolocal(&argvp)) {
  172.         return 0;
  173.     }
  174.     else {
  175.         pointer = &argvp + 1;
  176.         if (lexecv(argvp[0], pointer) == -1) {
  177.             if (dofile(argcp,&argvp) == -1) {
  178.                 puts(argvp[0]);
  179.                 puts(": not found\n");
  180.             }
  181.         return 0;
  182.         }
  183.     }
  184.     }
  185. return(-1);
  186. }
  187. dolocal(ptr)
  188. char *ptr[];
  189. {
  190. int value;
  191. char *tpoint;
  192.     if (strcmp(*ptr,"clr") == 0) {
  193.         puts(CLEARS);
  194.         return 1;
  195.     }
  196.     else if (strcmp(*ptr,"ccp") == 0) {
  197.         iop->_nocli = 1;    /* set no shell mode */
  198.         bios(1,0);        /* warm boot cpm */
  199.     }
  200.     else if (strcmp(*ptr,"exit") == 0) {
  201.         iop->_shsav = 0;    /* flush shell buffer */
  202.         bios(1,0);        /* warm boot cpm */
  203.     }
  204.     else if (**ptr == COMMENT) return 1;
  205.     else if (strcmp(*ptr,"logout") == 0) {
  206.         chdir('a');    /* set default directory */
  207.         execl("a:login",0);
  208.         ;
  209.         return 1;
  210.     }
  211.     else if (strcmp(*ptr,"echo") == 0) {
  212.         ++ptr;
  213.         while (*ptr != 0) {
  214.             puts(*ptr);
  215.             putchar(' ');
  216.             ptr++;
  217.         }
  218.         putchar('\n');
  219.         return 1;
  220.     }
  221.     else if (strcmp(*ptr,"pwd") == 0) {
  222.             putchar(pwd());    /* print current disk */
  223.             puts(":\n");
  224.             return 1;
  225.     }
  226.     else if (strcmp(*ptr,"cd") == 0) {
  227.             chdir(**++ptr);    /* set default disk */
  228.         return 1;
  229.     }
  230.     else if (strcmp(*ptr,"sleep") == 0) {
  231.         value = (SLEEPNO * atoi(*++ptr));
  232.         sleep(value);
  233.         return 1;
  234.     }
  235.     else if (strcmp(*ptr,"rm") == 0) {
  236.         ++ptr;    /* remove files */
  237.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  238.             puts("usage: rm [file] [file...]\n");
  239.             return 1;
  240.         }
  241.         while (*ptr != NULL && **ptr != NULL) {
  242.             expand(dozap,*ptr,0);
  243.             ptr++;
  244.         }
  245.     return 1;
  246.     }
  247.     else if (strcmp(*ptr,"lock") == 0) {
  248.         ++ptr;
  249.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  250.             puts("usage: lock [file] [file...]\n");
  251.             return 1;
  252.         }
  253.         while (*ptr != NULL && **ptr != NULL) {
  254.             expand(flock,*ptr,1);
  255.             ptr++;
  256.         }
  257.     return 1;
  258.     }
  259.     else if (strcmp(*ptr,"unlock") == 0) {
  260.         ++ptr;
  261.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  262.             puts("usage: unlock [file] [file...]\n");
  263.             return 1;
  264.         }
  265.         while (*ptr != NULL && **ptr != NULL) {
  266.             expand(flock,*ptr,0);
  267.             ptr++;
  268.         }
  269.     return 1;
  270.     }
  271.     else if (strcmp(*ptr,"mv") == 0) {
  272.         tpoint = *++ptr;
  273.         ++ptr;
  274.         value = *ptr;
  275.         if (tpoint == 0 || *tpoint == '\n' || **ptr == '\n' || *ptr == 0) {
  276.             puts("usage: mv [source] [dest]\n");
  277.             return 1;
  278.         }
  279.             if (index(tpoint,"*") != -1 || index(tpoint,"?") != -1) {
  280.                 puts(tpoint);
  281.                 puts(": ambiguous\n");
  282.                 return 1;
  283.             }
  284.             else if (index(value,"*") != -1 || index(value,"?") != -1) {
  285.                 puts(value);
  286.                 puts(": ambiguous\n");
  287.                 return 1;
  288.             }
  289.             else if (fstat(*ptr) == -1) {
  290.                 if ((value=fstat(tpoint)) == 1) {
  291.                     puts(tpoint);
  292.                     puts(": readonly\n");
  293.                     return 1;
  294.                 }
  295.                 else if (value == 0) {
  296.                     if (rename(tpoint,*ptr) == -1) {
  297.                         puts(*ptr);
  298.                         puts(": file not found\n");
  299.                         return 1;
  300.                     }
  301.                 }
  302.                 else if (value == -1) {
  303.                     puts(tpoint);
  304.                     puts(": file not found\n");
  305.                     return 1;
  306.                 }
  307.             }
  308.             else {
  309.                 puts(*ptr);
  310.                 puts(": file already exists\n");
  311.                 return 1;
  312.             }
  313.         return 1;
  314.     }
  315.     else if (strcmp(*ptr,"ls") == 0) {
  316.         ++ptr;
  317.         flag = 0; /* a kluge */
  318.         if (!(*ptr == 0 || **ptr == '\n' || **ptr == 0)) {
  319.             while (*ptr != NULL && **ptr != NULL) {
  320.                 expand(lst,*ptr,0);
  321.                 ptr++;
  322.             }
  323.             putchar('\n');
  324.         }
  325.         else {
  326.             expand(lst,"*.*",0);
  327.             putchar('\n');
  328.         }
  329.         return 1;
  330.     }
  331.     else if (strcmp(*ptr,"cat") == 0) {
  332.         ++ptr;
  333.         if (*ptr == 0 || **ptr